﻿using System;
using System.Windows.Forms;
using System.Xml;
using System.Configuration;
using System.Collections.Generic;
using System.Text;
using SdmxMl.Common;
using SdmxMl.Structure;
using SdmxMl.Helper;
using SdmxMl.Panels;
using SdmxMl.UC;
using SdmxMl.Multiplexor;
using SdmxMl.Registry;
using Ch.Admin.Bfs.Sms.Sdmx.IO.Xml;


namespace SdmxMl.Manager
{
    /// <summary>
    /// Class to manage Repository group menu items event and state
    /// </summary>
    public class RepositoryMenuManager
    {
        #region internal Members

        private ToolStripMenuItem GetArtefactMenuItem;
        private ToolStripMenuItem SubmitMenuItem;
        private ToolStripMenuItem SubmitAggregatedMenuItem;
        private ToolStripMenuItem ReserveArtefactMenuItem;
        private ToolStripMenuItem RepositorySourceMenuItem;
        private ToolStripMenuItem ImportImageContentMenuItem;
        private ToolStripMenuItem UpdateFinalizedMenuItem;
        private ToolStripMenuItem SubscribeMenuItem;

        private ToolStripButton GetArtefactButton;
        private ToolStripButton SubmitButton;
        private ToolStripButton ReserveArtefactButton;

        private TreeView tv;
        private ucPanelDetail panelDetail;

        private string ArtefactUtilityUrn;
        private string SubscribeUrl;
        private Form dlgSubscription;

     //   private SdmxMl.Check.DlgDiagnostic dlgDiagnostic;

        #endregion

        #region Constructor

        public RepositoryMenuManager(TreeView tree, ucPanelDetail panel)
        {
            tv = tree;
            panelDetail = panel;
            if (ConfigurationManager.AppSettings["UtilityUrl"] != null &&
                ConfigurationManager.AppSettings["UtilityUrl"].ToString().Trim() != string.Empty)
                ArtefactUtilityUrn = ConfigurationManager.AppSettings["UtilityUrl"].ToString().Trim();

            if (ConfigurationManager.AppSettings["SubscribeUrl"] != null &&
                ConfigurationManager.AppSettings["SubscribeUrl"].ToString().Trim() != string.Empty)
                SubscribeUrl = ConfigurationManager.AppSettings["SubscribeUrl"].ToString().Trim();

        }
        #endregion

        #region Assign Menus

        /// <summary>
        /// Assign menu items associated to repository
        /// </summary>
        public void assignMenuItems(ToolStripMenuItem getArtefactItem,
            ToolStripMenuItem submitArtefactItem,
            ToolStripMenuItem submitAggregatedItem,
            ToolStripMenuItem reserveArtefactItem,
            ToolStripMenuItem repositorySourceItem,
            ToolStripMenuItem updateFinalizedItem,
            ToolStripMenuItem importImageContentItem,
            ToolStripMenuItem SubscribeChanges)
        {
            GetArtefactMenuItem = getArtefactItem;
            if (GetArtefactMenuItem != null)
                GetArtefactMenuItem.Click += new EventHandler(GetArtefactMenuItem_Click);

            SubmitMenuItem = submitArtefactItem;
            if (SubmitMenuItem != null)
                SubmitMenuItem.Click += new EventHandler(SubmitArtefactMenuItem_Click);

            SubmitAggregatedMenuItem = submitAggregatedItem;
            if (SubmitAggregatedMenuItem != null)
                SubmitAggregatedMenuItem.Click += new EventHandler(SubmitAggregatedMenuItem_Click);

            ReserveArtefactMenuItem = reserveArtefactItem;
            if (ReserveArtefactMenuItem != null)
                ReserveArtefactMenuItem.Click += new EventHandler(ReserveArtefactMenuItem_Click);

            RepositorySourceMenuItem = repositorySourceItem;
            if (RepositorySourceMenuItem != null)
                RepositorySourceMenuItem.Click += new EventHandler(RepositorySourceMenuItem_Click);
            RepositorySourceMenuItem.Enabled = Mux.Instance.State != MultiplexorState.Unused;
            ImportImageContentMenuItem = importImageContentItem;
            if (ImportImageContentMenuItem != null)
                ImportImageContentMenuItem.Click += new EventHandler(ImportImageContentMenuItem_Click);

            UpdateFinalizedMenuItem = updateFinalizedItem;
            if (UpdateFinalizedMenuItem != null)
                UpdateFinalizedMenuItem.Click += new EventHandler(UpdateFinalizedMenuItem_Click);

            if (ReserveArtefactMenuItem != null)
                ReserveArtefactMenuItem.Click += new EventHandler(ReserveArtefactMenuItem_Click);

            SubscribeMenuItem = SubscribeChanges;
            if (SubscribeMenuItem != null)
                SubscribeMenuItem.Click += new EventHandler(SubscribeChanges_Click);

            UpdateMenuItemsState();
        }

        public void AssignButtons(ToolStripButton getArtefact, ToolStripButton submitArtefact, ToolStripButton reserveArtefact)
        {
            GetArtefactButton = getArtefact;
            SubmitButton = submitArtefact;
            ReserveArtefactButton = reserveArtefact;

            if (GetArtefactButton != null)
                GetArtefactButton.Click += new EventHandler(GetArtefactMenuItem_Click);
            if (SubmitButton != null)
                SubmitButton.Click += new EventHandler(SubmitArtefactMenuItem_Click);
            if (ReserveArtefactButton != null)
                ReserveArtefactButton.Click += new EventHandler(ReserveArtefactMenuItem_Click);

            UpdateMenuItemsState();
        }

        #endregion

        #region Update items state

        public void UpdateMenuItemsState()
        {
            //bool repositoryActiv = TinyRegistryProxy.State == RepositoryState.Ok;
            bool repositoryActiv = Mux.Instance.RunningOK;
            bool isArefact = tv != null && tv.SelectedNode != null &&
                (tv.SelectedNode.Tag is Artefact && repositoryActiv);

            // Getting artefact from registry
            if (GetArtefactMenuItem != null)
                GetArtefactMenuItem.Enabled = repositoryActiv;
            if (GetArtefactButton != null)
                GetArtefactButton.Enabled = repositoryActiv;

            // Submit Artefact
            if (SubmitMenuItem != null)
                SubmitMenuItem.Enabled = isArefact;
            if (SubmitButton != null)
                SubmitButton.Enabled = isArefact;
            if (SubmitAggregatedMenuItem != null)
            {
                SubmitAggregatedMenuItem.Enabled = isArefact && Mux.Instance.UserIsAdmin;
            }

            // Reserve artefact
            if (ReserveArtefactMenuItem != null)
                ReserveArtefactMenuItem.Enabled = isArefact;
            if (ReserveArtefactButton != null)
                ReserveArtefactButton.Enabled = isArefact;

            // Import image
            if (ImportImageContentMenuItem != null)
                ImportImageContentMenuItem.Enabled = repositoryActiv;

            // Update text of finalized artefact
            if (UpdateFinalizedMenuItem != null)
                UpdateFinalizedMenuItem.Enabled = (string.IsNullOrEmpty(ArtefactUtilityUrn) == false || Mux.IsNewSmsRegistry) && isArefact;
            if (SubscribeMenuItem != null)
                SubscribeMenuItem.Enabled = string.IsNullOrEmpty(SubscribeUrl) == false || Mux.IsNewSmsRegistry;
        }

        #endregion

        #region Submit Artefact(s)

        /// <summary>Transmit artefact to registry </summary>
        /// <param name="sender"></param> <param name="e"></param>
        private void SubmitArtefactMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                 SubmitArtefactToRegistry();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        public void CheckArtefact(out Artefact a, out ArtefactManager arm)
        {
            a = null;
            arm = null;
            //if (tv.SelectedNode != null && tv.SelectedNode.Parent != null)
            //{
            //    a = tv.SelectedNode.Tag as Artefact;
            //    arm = tv.SelectedNode.Parent.Tag as ArtefactManager;
            //    if (a != null && arm != null)
            //    {
            //        // Update artefact from detail view
            //        panelDetail.UpdateNodeTag(tv.SelectedNode);

            //        // Check valid SMS artefact
            //        List<SdmxInformationMessage> diagList = null;
            //        using (new CWaitCursor())
            //        {
            //            ArtefactChecker checker = new ArtefactChecker();
            //            diagList = checker.Check(a);
            //        }
            //        if (diagList != null) // && diagList.Count > 0)
            //        {
            //            SdmxMl.Check.DlgDiagnostic aDlg = new Check.DlgDiagnostic();

            //            if (dlgDiagnostic == null)
            //            {
            //                dlgDiagnostic = new Check.DlgDiagnostic();
            //                dlgDiagnostic.FormClosed += new FormClosedEventHandler(dlgDiagnostic_FormClosed);
            //            }

            //            dlgDiagnostic.BindDiagnostic(diagList);
            //            dlgDiagnostic.Focus();
            //            dlgDiagnostic.Show();
            //        }
            //    }
            //}
       }

        void dlgDiagnostic_FormClosed(object sender, FormClosedEventArgs e)
        {
            //dlgDiagnostic.FormClosed -= new FormClosedEventHandler(dlgDiagnostic_FormClosed);
            //dlgDiagnostic = null;
        }
  
        /// <summary>
        /// Export Artefact to Registry. If already exists, a confirmation must be given.
        /// If artefact has references to others artefacts, they must be already present
        /// in registry.
        /// </summary>
        public void SubmitArtefactToRegistry()
        {
            Artefact a = null;
            ArtefactManager arm = null;
            if (tv.SelectedNode != null && tv.SelectedNode.Parent != null)
            {
                if (panelDetail != null)
                    panelDetail.UpdateNodeTag(tv.SelectedNode);

                a = tv.SelectedNode.Tag as Artefact;
                arm = tv.SelectedNode.Parent.Tag as ArtefactManager;

                if (a != null && arm != null)
                {
                    // Update or create in registry
                    bool alreadyExist = Mux.Instance != null && Mux.Instance.ExistArtefact(arm.ArtefactType.ToString(), a.FullIdent);
                    string ownerId = string.Empty;
                    OwnerGroupHelper ownerGrouphelper = new OwnerGroupHelper();
                    if (Mux.IsNewSmsRegistry && alreadyExist == false)
                        ownerId = ownerGrouphelper.SelectOwner();

                    if (AuthoriseRegistry.RequestCredential(panelDetail.Parent, alreadyExist))
                    {
                        using (new CWaitCursor())
                        {
                            XmlDocument xDoc = arm.GetAsDocument(a);
                            if (AuthoriseRegistry.UnlockOnlySelected)
                            {
                                Mux.Instance.UndoCheckOut(arm.ArtefactType.ToString(), a.FullIdent);
                                // Icon for remembering checked In
                                a.RegCheckState = CheckInOutState.CheckIn;
                                tv.SelectedNode.ImageIndex = tv.SelectedNode.SelectedImageIndex = 19;
                            }
                            else
                            {
                                // Check Dependencies of artefact (No dependencies for Meta set)
                                ArtefactRefTypedList refList = a.ArtefactRefList;
                                foreach (ArtefactRefTyped art in refList)
                                    if (Mux.Instance.ExistArtefact(art.Type.ToString(), art.FullIdent))
                                        art.IsLoaded = true;

                                if (refList.FullyLoaded == false)
                                {
                                    string head = "Some artefact references are not present in Registry." + Environment.NewLine +
                                        "For coherence they are required." + Environment.NewLine;
                                    MessageBox.Show(head + refList.MissingListMessage, "Error");
                                }
                                else
                                {
                                    if (AuthoriseRegistry.BackupRequired)
                                        Mux.Instance.SubmitArtefactBackup(arm.ArtefactType.ToString(), a.FullIdent, xDoc);
                                    else
                                        Mux.Instance.SubmitArtefact(arm.ArtefactType.ToString(), a.FullIdent, xDoc);

                                    // New registry, set Ownership
                                    if (Mux.IsNewSmsRegistry && alreadyExist == false)
                                    {
                                        ownerGrouphelper.UpdateOwner(arm.ArtefactType, a.FullIdent, ownerId);
                                    }

                                    // Icon for remembering checked In
                                    a.RegCheckState = CheckInOutState.CheckIn;
                                    tv.SelectedNode.ImageIndex = tv.SelectedNode.SelectedImageIndex = 19;

                                    // Key checking for (meta)dataset

                                }
                            }
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Export whole memory project as artefact document. If already exists, a confirmation must be given.
        /// If selected artefact has references to others artefacts, they must be already present
        /// in registry.
        /// </summary>
        void SubmitAggregatedMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                using (new CWaitCursor())
                {
                    Artefact a = tv.SelectedNode.Tag as Artefact;
                    ArtefactManager arm = tv.SelectedNode.Parent.Tag as ArtefactManager;
                    if (a != null && arm != null)
                    {
                        if (MessageBox.Show("Caution: Please confirm that the whole project (all artefacts) has to be saved as a unique aggregated document" +
                            Environment.NewLine + "Identified as: " + a.FullIdent, "Confirmation", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.OK)
                        {
                            // Update 
                            panelDetail.UpdateNodeTag(tv.SelectedNode);

                            if (AuthoriseRegistry.RequestCredential(panelDetail.Parent, Mux.Instance.ExistArtefact(arm.ArtefactType.ToString(), a.FullIdent)))
                            {
                                if (AuthoriseRegistry.UnlockOnlySelected)
                                {
                                    Mux.Instance.UndoCheckOut(arm.ArtefactType.ToString(), a.FullIdent);
                                }
                                else
                                {
                                    // Load Dependencies of artefact
                                    ArtefactRefTypedList refList = a.ArtefactRefList;
                                    SmManager smManager = new SmManager();
                                    smManager.RemoveArtefactRefAlreadyInRepository(refList);
                                    smManager.LoadMissingArtefactsFromReferenceMgr(refList);
                                    smManager.PutArtefact(arm.ArtefactType, a);

                                    if (refList.FullyLoaded == false)
                                    {
                                        string head = "Some artefact references are not present in memory. For coherence they are required." + Environment.NewLine;
                                        throw new ApplicationException(head + refList.MissingListMessage);
                                    }
                                    else
                                    {
                                        // Load Copy of what in tree, Already in registry are flagged as external ref
                                        SmManager sm = ReferenceManager.GetContainerWithRegistryProxy(a);
                                        XmlDocument xDoc = sm.GetAsDocument();

                                        if (AuthoriseRegistry.BackupRequired)
                                            Mux.Instance.SubmitArtefactBackup(arm.ArtefactType.ToString(), a.FullIdent, xDoc);
                                        else
                                            Mux.Instance.SubmitArtefact(arm.ArtefactType.ToString(), a.FullIdent, xDoc);
                                    }
                                }
                                // Icon for remembering checked In
                                a.RegCheckState = CheckInOutState.CheckIn;
                                tv.SelectedNode.ImageIndex = tv.SelectedNode.SelectedImageIndex = 19;
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
 
        #endregion

        #region Get Artefact via dialog

        private void GetArtefactMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                DlgGetArtefact aDlg = new DlgGetArtefact(ReferenceManager.TreeMgr);
                aDlg.Show();
                UpdateMenuItemsState();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        #endregion

        #region Subscribe

        void SubscribeChanges_Click(object sender, EventArgs e)
        {
            try
            {
                if (dlgSubscription == null)
                {
                    dlgSubscription = Mux.IsNewSmsRegistry ? (Form) new DlgSubscription() : (Form) new DlgSubscribe(SubscribeUrl);
                    dlgSubscription.FormClosed += new FormClosedEventHandler(dlgSubscription_FormClosed);
                }
                
               // DlgSubscribe aDlg = new DlgSubscribe(SubscribeUrl);
               // aDlg.ShowDialog();

                dlgSubscription.WindowState = FormWindowState.Normal;
                dlgSubscription.Focus();
                dlgSubscription.Show(panelDetail.Parent);

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

        }

        void dlgSubscription_FormClosed(object sender, FormClosedEventArgs e)
        {
            dlgSubscription = null;
        }

        #endregion


        #region Reserve Artefact

        /// <summary>
        /// Reserve an existing artefact of the registry for modifications
        /// </summary>
        /// <param name="sender"></param><param name="e"></param>
        void ReserveArtefactMenuItem_Click(object sender, EventArgs e)
        {
            if (tv.SelectedNode != null)
            {

                Artefact a = tv.SelectedNode.Tag as Artefact;
                if (a != null)
                {
                    try
                    {
                        // Update currently edited
                        panelDetail.UpdateNodeTag(tv.SelectedNode);

                        using (new CWaitCursor())
                        {
                            ArtefactManager arm = tv.SelectedNode.Parent.Tag as ArtefactManager;

                            // If artefact already in memory ask for refresh
                            TreeNode targetNode = tv.SelectedNode;
                            if (MessageBox.Show("Artefact is already in memory, refresh it with Repository Version ?", "Repository", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) == DialogResult.Yes)
                            {
                                XmlDocument xDoc = Mux.Instance.GetArtefact(arm.ArtefactType.ToString(), a.FullIdent);

                                SmManager sm = new SmManager();
                                sm.LoadSdmxDocument(null, true, xDoc);

                                if (arm != null)
                                {
                                    arm.ArtefactList.Remove(a);
                                    targetNode.Parent.Nodes.Remove(targetNode);
                                }

                                object ob = NavigationManager.LoadFromSmManager(sm);
                                NavigationManager.RequestNavigation(ob);
                            }

                            Mux.Instance.CheckOut(arm.ArtefactType.ToString(), a.FullIdent);
                            // Icon for remembering checked In
                            a.RegCheckState = CheckInOutState.CheckOut;
                            tv.SelectedNode.ImageIndex = tv.SelectedNode.SelectedImageIndex = 18;
                        }
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                }
            }
        }
        #endregion

        #region Defines Repository source

        /// <summary> Redefine repository source </summary>
        /// <param name="sender"></param> <param name="e"></param>
        public void RepositorySourceMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                DlgTinyRegistryConfig aDlg = new DlgTinyRegistryConfig();
                aDlg.ShowDialog(tv.Parent);

                //Now update menu enabling
                if (tv != null && tv.SelectedNode == null && tv.Nodes.Count > 0)
                    tv.SelectedNode = tv.Nodes[0];
                else
                {
                    ReferenceManager.TreeMgr.RefreshDetailView();
                }
                UpdateMenuItemsState();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        #endregion

        #region Repository Image

        // DEC 03.08.2011
        /// <summary>
        /// Import to a directory a complete image of repository content
        /// </summary>
        /// <param name="sender"></param><param name="e"></param>
        private void ImportImageContentMenuItem_Click(object sender, EventArgs e)
        {
            //TODO IREGISTRY
            try
            {
                //if (Mux.Instance.ConfigMultiplexed == false)
                //{
                //    DlgImportRepository aDlg = new DlgImportRepository();
                //    aDlg.ShowDialog();
                //}
                //else
                {

                    dlgGroupSelect aDlg = new dlgGroupSelect();
                    if (aDlg.ShowDialog() == DialogResult.OK)
                    {

                        if (aDlg.orgNsi != null)
                        {
                            foreach (OrganisationType o in aDlg.orgNsi.Agencies)
                            {
                                string subDir = aDlg.SelectedFolder + "\\" + o.Id;
                                if (System.IO.Directory.Exists(subDir) == false)
                                    System.IO.Directory.CreateDirectory(subDir);



                                using (new SdmxMl.Helper.CWaitCursor())
                                {
                                    GroupMetaTransfer groupTfer = new GroupMetaTransfer(subDir, o.Id,
                                        Mux.Instance);
                                    groupTfer.LoadDirInfoImages();
                                }
                            }

                        }

                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        #endregion

        #region Update Texts in finalized Artefact

        void UpdateFinalizedMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                Artefact a = tv.SelectedNode.Tag as Artefact;
                ArtefactManager arm = tv.SelectedNode.Parent.Tag as ArtefactManager;
                if (a != null && arm != null)
                {
                    using (new CWaitCursor())
                    {
                        Mux.Instance.UpdateFinalizedArtefact(a.ArType.ToString(), a.FullIdent, arm.GetAsDocument(a));
                        MessageBox.Show("Finalized artefact updated in registry.", "Finalization update", MessageBoxButtons.OK, MessageBoxIcon.Information);

                    }
                }
                else throw new ApplicationException("No artefact selected");
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        

        #endregion

    }
}
